//============================================================================
// Name        : geodbfs.cpp
// Author      : T.Freygang
// Version     : 1.0
// Copyright   : LGPL
// Description : geodbfs in C++
//============================================================================


/** include config.h **/
#include "config.h"

/**
 * C++-Headers
 **/
#include <iostream>
#include <cstdio>
#include <vector>

/**
 * Boost-Library
 * url: http://www.boost.org/
 * programm options
 **/

#include <boost/program_options.hpp>


#include <ogrsf_frmts.h>
#include "Filesystem.h"

namespace po = boost::program_options;


/**
 * main function
 **/

int main(int argc, char* argv[])
{
	std::cout << "GDAL OGR Version: " << GDAL_VERSION_MAJOR;
	std::cout << GDAL_VERSION_MINOR;
	std::cout << GDAL_VERSION_REV << std::endl;

    String database_type;
    String host;
    String port;
    String database;
    String username;
    String password;
    String geomFieldName;
	String cacheDirName;
	size_t cacheLifeTime;

    bool debug = false;

    /**
     * command line parser options
     **/
    po::options_description general_desc("General options");
    general_desc.add_options()
        ("foreground,f", "Foreground")
        (",o", po::value<String>(), "Fuse Options")
        ("help,h", "produce help")
        ("version,v", "Version")
        ("debug,d", "debug mode")
        ("geoname", po::value<String>(&geomFieldName)->default_value("geom"), "Geometry fieldname (Write)")
		("cachedir", po::value<String>(&cacheDirName)->default_value("cache"), "set cache dir name")
		("cache-lifetime,t", po::value<size_t>(&cacheLifeTime)->default_value(10), "set cache life time in second[default: 10]")
    ;

    po::options_description database_desc("Database options");
    database_desc.add_options()
        ("type",     po::value<String>(&database_type)->default_value(""), "Database Type")
        ("host",     po::value<String>(&host)->default_value("localhost"), "Hostname")
        ("port",     po::value<String>(&port)->default_value(""), "Port")
        ("database", po::value<String>(&database)->default_value(""), "Database")
        ("user",     po::value<String>(&username)->default_value(""), "Username")
        ("password", po::value<String>(&password)->default_value(""), "password")
    ;

    po::options_description all_desc("geodbfs usage: geodbfs [options] [Mount Point]\n"
									 "Mount Point e.g. \n"
									#ifdef WINDOWS
									 " \t\t geodbfs [options] m:\\ \n"
									 "\t\t geodbfs [options] c:\\path\\to (only NTFS and no slash at the end)"
									#else
										"\t\t /path/to/dir"
									#endif
	);
    all_desc.add(general_desc).add(database_desc);

    po::variables_map vm;
    po::store( po::parse_command_line(argc, argv, all_desc), vm);
    po::notify(vm);

    cacheLifeTime = cacheLifeTime * 1000;
    /**
     * option error check
     **/
    if(vm.count("help")){
        std::cout << all_desc << std::endl;
        return 0;
    }

	if(port.compare("") == 0 && database_type.compare("") != 0)
	{
		#ifdef ENABLE_MYSQL
		if(database_type.compare("mysql") == 0) {
			port = "3306";
		}
		#endif
		#ifdef ENABLE_POSTGRESQL
		if(database_type.compare("pgsql") == 0) {
			port = "5432";
		}
		#endif
	}

    if(database_type.compare("") == 0 || (database_type.compare("mysql") == 0 || database_type.compare("oracle") == 0 || database_type.compare("pgsql") == 0) == false || host.compare("") == 0 || port.compare("") == 0 || database.compare("") == 0 || username.compare("") == 0 || password.compare("") == 0)
    {
        std::cout << all_desc << std::endl << std::endl;
        std::cout << "current options:" << std::endl;
        std::cout << "\ttype:     " << database_type << std::endl;
        std::cout << "\thost:     " << host << std::endl;
        std::cout << "\tport:     " << port << std::endl;
        std::cout << "\tdatabase: " << database << std::endl;
        std::cout << "\tuser: " << username << std::endl;
        std::cout << "\tpassword: " << password << std::endl;
		std::cout << "\tmount point: " << argv[argc-1] << std::endl;

        if(database_type.compare("") == 0)
        {
            std::cout << "error missing: --type [";
            #ifdef ENABLE_MYSQL
            std::cout << "mysql";
            #endif

            #ifdef ENABLE_POSTGRESQL
                #ifdef ENABLE_MYSQL
                    std::cout << ", ";
                #endif
            std::cout << "pgsql";
            #endif

            #ifdef ENABLE_ORACLE
                #if defined(ENABLE_MYSQL) || defined(ENABLE_POSTGRESQL)
                    std::cout << ", ";
                #endif
            std::cout << "oracle";
            #endif

            std::cout << "]" << std::endl;
        }
        else{
            bool test = false;
            #ifdef ENABLE_MYSQL
            if(database_type.compare("mysql") == 0){
                test = true;
            }
            #endif
            #ifdef ENABLE_ORACLE
            if(database_type.compare("oracle") == 0){
                test = true;
            }
            #endif
            #ifdef ENABLE_POSTGRESQL
            if(database_type.compare("pgsql") == 0){
                test = true;
            }
            #endif
            if(test == false)
            {
                std::cout << "error unknow database type: " << database_type << std::endl;
            }
        }
        if(host.compare("") == 0) std::cout << "error missing: --host" << std::endl;
        if(port.compare("") == 0) std::cout << "error missing: --port" << std::endl;
        if(database.compare("") == 0) std::cout << "error missing: --database" << std::endl;
        if(username.compare("") == 0) std::cout << "error missing: --user" << std::endl;
        if(password.compare("") == 0) std::cout << "error missing: --password" << std::endl;
        return 0;
    }


    std::cout << "debug verbose: ";
    if(vm.count("debug")) {
        debug = true;
        std::cout << "on";
    }
    else
    {
        std::cout << "off";
    }
    std::cout << std::endl;
    /**
     * FUSE/Dokan options
     */
    std::vector<char *> arg_options;

    //add Programm File
    arg_options.push_back(argv[0]);

    //add foreground fuse option
    if(vm.count("foreground")) {
        char f_option[] = "-f";
        arg_options.push_back(f_option);
    }
    // add mountpoint
    arg_options.push_back(argv[argc-1]);


    /**
     * mount filesystem
     */

    Filesystem filesystem(&database_type, &host, &port, &database, &username, &password, &cacheDirName, &geomFieldName, argc, argv, cacheLifeTime, debug);
	if(filesystem.getDBConnection() != NULL && filesystem.getDBConnection()->isConnected(database))
	{
		return filesystem.mount(arg_options.size(), &arg_options.front());
	}
	else
	{
		std::cout << "could not Connected to Database: " << database << std::endl;
		return -1;
	}
}


